<script setup>
import { ref, onMounted, computed } from 'vue'
import { throttle } from '@/utils'
import axios from 'axios';

let itemHeight = ref(40)
let allListData = ref([])
let top = ref(0)
let start = ref(0)
let count = ref(10)
let scrollBoxRef = ref(null)
let listData = computed(() => (allListData.value.slice(start.value, start.value + count.value)))

/**
 * 逻辑：计算滚动条的起始位置和终止位置，截取渲染
 */
onMounted(() => {
    init()
})

const init = async() => {
    const { data } = await axios.get('/api/getList')
    allListData.value = data.data
}

const scroll = throttle(() => {
    // 首先计算外面盒子的滚动条高度
    let scrollTop = scrollBoxRef.value.scrollTop
    // 通过（总的滑动距离/单个元素的高度）向下取整 + count，也就是 （scrollTop + ）/listItem 得到的是当前滑动到哪一条数据了
    start.value = Math.floor(scrollTop / itemHeight.value) + count.value
    top.value = scrollTop
}, 20)

</script>

<template>
    <!-- 最外面固定高度盒子
         比如1条数据的高度是40px,一页想要展示10条，那么最外面盒子的高度就是 400px
         要开启定位和滚动
    -->
    <div class="scrollBox" @scroll="scroll" ref="scrollBoxRef" :style="{height: itemHeight * count + 'px'}">
        <!-- 所有列表的占位盒子
             一个高度是40，10万条数据的高度是 100000 * 40
         -->
        <div class="allListBox" :style="{height: itemHeight * allListData.length + 'px'}"></div>
        <!-- 呈现在页面上的数据盒子 
             一共10条
        -->
        <div class="listBox" :style="{top: top + 'px'}">
            <div class="listItem" :style ="{height: itemHeight + 'px'}" v-for="item, index in listData" :key="index">{{ item.name }}</div>
        </div>
    </div>
</template>

<style lang="less" scoped>
    .scrollBox{
        width: 400px;
        position: relative;
        overflow: scroll;
        .listBox{
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            .listItem{
                width: 100%;
                color: #fff;
                font-size: 14px;
            }
            .listItem:nth-child(n){
                background: green;
            }
            .listItem:nth-child(2n){
                background: palevioletred;
            }
        }
    }
</style>